import { router } from "@/router";
import { message } from "ant-design-vue";
import axios, { AxiosRequestConfig, AxiosResponse } from "axios";
import qs from "qs";

const instance = axios.create({
  withCredentials: true,
  timeout: 30000,
  responseType: "json",
  baseURL: import.meta.env.MODE === "dev" ? "/p" : "",
});

// 声明一个 Map 用于存储每个请求的标识 和 取消函数
const pending = new Map();
/**
 * 添加请求
 * @param {Object} config
 */
const addPending = (config: AxiosRequestConfig) => {
  const url = [
    config.method,
    config.url,
    qs.stringify(config.params),
    qs.stringify(config.data),
  ].join("&");
  config.cancelToken =
    config.cancelToken ||
    new axios.CancelToken((cancel) => {
      if (!pending.has(url)) {
        // 如果 pending 中不存在当前请求，则添加进去
        pending.set(url, cancel);
      }
    });
};
/**
 * 移除请求
 * @param {Object} config
 */
const removePending = (config: AxiosRequestConfig) => {
  const url = [
    config.method,
    config.url,
    qs.stringify(config.params),
    qs.stringify(config.data),
  ].join("&");
  if (pending.has(url)) {
    // 如果在 pending 中存在当前请求标识，需要取消当前请求，并且移除
    const cancel = pending.get(url);
    cancel(url);
    pending.delete(url);
  }
};

/**
 * 清空 pending 中的请求（在路由跳转时调用）
 */
const clearPending = () => {
  for (const [url, cancel] of pending) {
    cancel(url);
  }
  pending.clear();
};

// 重新请求
const retryRequest = async (error: any, response: any) => {
  const config = error.config;
  // 全局的请求次数,请求的间隙
  const [RETRY_COUNT, RETRY_DELAY] = [1, 1000];

  if (config && RETRY_COUNT) {
    // 设置用于跟踪重试计数的变量
    config.__retryCount = config.__retryCount || 0;
    // 检查是否已经把重试的总数用完
    if (config.__retryCount >= RETRY_COUNT) {
      return Promise.reject(response || { message: error.message });
    }
    // 增加重试计数
    config.__retryCount++;
    // 创造新的Promise来处理指数后退
    const backoff = new Promise<void>((resolve) => {
      setTimeout(() => {
        resolve();
      }, RETRY_DELAY || 1);
    });
    // instance重试请求的Promise
    await backoff;
    return await instance(config);
  }
};
// 添加请求拦截器
instance.interceptors.request.use(
  (request) => {
    removePending(request); // 在请求开始前，对之前的请求做检查取消操作
    addPending(request);
    return request;
  },
  (error) => {
    return Promise.reject(error);
  }
);

// 添加响应拦截器
instance.interceptors.response.use(
  (response: AxiosResponse) => {
    removePending(response as AxiosRequestConfig); // 在请求结束后，移除本次请求
    return response;
  },
  (error) => {
    const response = error.response;
    if (!response) {
      console.error(error);
      return false;
    }
    const errorCode = [301, 302, 400, 401, 403, 404, 500, 501, 502];
    if (error.message === "操作太频繁，请稍后再试") {
      // 被cancel的情况
      return false;
    }
    // 根据返回的http状态码做不同的处理
    switch (response.status) {
      case 401:
      case 402:
        router.push("/login");
        break;
      case 403:
        message.error(response.statusText || "参数不正确");
        break;
      case 500:
        if (
          [
            "/certificate/custom-html",
            "/certificate/down",
            "/certificate/view",
          ].includes(response.config.url)
        ) {
          break;
        }
        message.error(response.statusText || "服务500");
        // 服务端错误
        break;
      case 502:
        message.error(response.statusText || "服务502");
        // 服务端错误
        break;
      default:
        break;
    }
    if (errorCode.includes(response.status)) return false;
    // 超时重新请求
    retryRequest(error, response);
    return Promise.reject(response || { message: error.message });
  }
);

export { instance, clearPending };
